// Firefox about:config

// network.proxy.autoconfig_url=file:///sdcard/archive/android.pac # on android
// network.proxy.autoconfig_url=file://E:/workspace/rogerxu-hg/rules/android.pac # on windows

// network.proxy.type=0 # Direct connection, no proxy.
// network.proxy.type=1 # Manual proxy configuration.
// network.proxy.type=2 # Proxy auto-configuration (PAC).
// network.proxy.type=4 # Auto-detect proxy settings.
// network.proxy.type=5 # Use system proxy settings. (Default in Linux; default for all platforms, starting in 1.9.2.4 /Firefox 3.6.4)


// namespace
var demo = {};
demo.pac = {};

// proxy server IP
demo.pac.PROXY_SERVER_IP = '192.168.1.30';

// Protocol enum
demo.pac.Protocol = {
    DIRECT: 'DIRECT',
    PROXY: 'PROXY',
    SOCKS5: 'SOCKS5'
};

// Util class
demo.pac.Util = {};

// Util.replace
demo.pac.Util.replace = function(tmpl, map, pattern) {
    var _pattern = /\{([^\}]+)\}/g;

    var output = tmpl.replace(pattern || _pattern, function(str, key) {
        return map[key] || '';
    });

    return output;
};

// Util.getDomain
demo.pac.Util.getDomain = function(host) {
    // twitter.com -> twitter.com
    // www.twitter.com -> twitter.com

    var domain = null;
    var patternExp = /[^\.]\w+\.\w+$/;

    var result = patternExp.exec(host);
    if (result) {
        domain = result[0] || null;
    }

    return domain;
};

function getProxyMap() {
    var Util = demo.pac.Util; // shortcut
    var serverIP = demo.pac.PROXY_SERVER_IP; // shortcut
    var Protocol = demo.pac.Protocol; // shortcut

    var proxyPattern = '{0} {1}:{2}';

    var proxyMap = {};
    proxyMap['DIRECT'] = Protocol.DIRECT;
    proxyMap['SSH'] = Util.replace(proxyPattern, [Protocol.SOCKS5, serverIP, 7070]);
    proxyMap['Polipo'] = Util.replace(proxyPattern, [Protocol.PROXY, serverIP, 8123]);
    proxyMap['WallProxy'] = Util.replace(proxyPattern, [Protocol.PROXY, serverIP, 8086]);
    proxyMap['GFWProxy'] = Util.replace(proxyPattern, [Protocol.PROXY, 'gfw-proxy.co.cc', 3128]);

    return proxyMap;
}

// Proxy class
demo.pac.Proxy = getProxyMap();


function regExpMatch(url, pattern) {
    try {
        return new RegExp(pattern).test(url);
    } catch (ex) {
        return false;
    }
}

function getProxyForHttps(domain, url, host) {
    var Proxy = demo.pac.Proxy; // shortcut
    var Util = demo.pac.Util; // shortcut

    // https
    if (shExpMatch(url, Util.replace('https://{0}', [domain])) // https://example.com
            || shExpMatch(url, Util.replace('https://{0}/*', [domain])) // https://example.com/*
            || shExpMatch(url, Util.replace('https://*.{0}', [domain])) // https://*.example.com
            || shExpMatch(url, Util.replace('https://*.{0}/*', [domain])) // https://*.example.com/*
    ) {
        return Proxy.Polipo;
    }

    return null;
}

function getProxyForDomain(domain, url, host) {
    var Proxy = demo.pac.Proxy; // shortcut
    var Util = demo.pac.Util; // shortcut

    // https
    var _proxy = getProxyForHttps(domain, url, host);
    if (_proxy) return _proxy;

    // http
    if (host === domain // example.com
            || dnsDomainIs(host, Util.replace('.{0}', [domain])) // *.example.com
    ) { 
        return Proxy.WallProxy;
    }

    return null;
}

// handle domain
function FindProxyForDomain(url, host) {
    var Util = demo.pac.Util; // shortcut
    var proxy = null;

    var domain = Util.getDomain(host);

    switch (domain) {
    case 'appspot.com':
    case 'blogger.com':
    case 'blogspot.com':
    case 'facebook.com':
    case 'fbcdn.com':
    case 'feedburner.com':
    case 'google-analytics.com':
    case 'googleapis.com':
    case 'googlecode.com':
    case 'googlegroups.com':
    case 'googleusercontent.com':
    case 'twitter.com':
    case 'twimg.com':
    case 'wapedia.mobi':
    case 'youtube-nocookie.com':
    case 'ytimg.com':
        proxy = getProxyForDomain(domain, url, host);
        break;
    default:
        // empty
    }

    return proxy;
}

// main function
function FindProxyForURL(url, host) {
    var Proxy = demo.pac.Proxy; // shortcut
    var Util = demo.pac.Util; // shortcut
    var url = url.toLowerCase(); // url=>https://bbs.operachina.com/viewtopic.php?f=30&t=85045
    var host = host.toLowerCase(); // host=>bbs.operachina.com
    var _proxy = null;

    // domain
    _proxy = FindProxyForDomain(url, host);
    if (_proxy) return _proxy;

    // Google Docs
    _proxy = getProxyForDomain('docs.google.com', url, host);
    if (_proxy) return _proxy;

    // YouTube
    if (shExpMatch(host, '*.c.youtube.com')) return Proxy.SSH; // *.c.youtube.com

    _proxy = getProxyForHttps('youtube.com', url, host); // https://*.youtube.com
    if (_proxy) return _proxy;

    if (shExpMatch(url, 'http://*youtube.com*')) return Proxy.WallProxy; // url contains youtube.com

    // Google Https
    _proxy = getProxyForHttps('google.com', url, host);
    if (_proxy) return _proxy;

    // BBC
    if (shExpMatch(url, '*://www.bbc.co.uk/zhongwen/*')) return Proxy.WallProxy;

    //if (regExpMatch(url, '^[\w\-]+:\/+(?!\/)(?:[^\/]+\.)?www\.exblog\.jp')) return 'DIRECT';
    //if (regExpMatch(url, '^[\w\-]+:\/+(?!\/)(?:[^\/]+\.)?ipv6\.google\.com')) return 'DIRECT';
    //if (regExpMatch(url, '^http://wordpress\.com')) return 'DIRECT';
    //if (regExpMatch(url, '^https://wordpress\.com')) return 'DIRECT';

    return Proxy.DIRECT;
}